#include <iostream>
#include "com/properties.h"
#include "sms_server.h"
#include <string>
#include "com/simple_logger.h"
#include "transmit/net_bus.h"
#include "app_context.h"
#include "encrypt/crypto_graphic.h"
#include <cstdio>
#include "com/file_utils.h"
#include "stream/stream_service.h"
#include <list>
#include <thread>

using namespace std;

void GenerateEncrypt();
void InitLogger();
void InitAlias();
void Boot();

// 启动
int main(int argc, char *argv[])
{
    InitLogger();
    GenerateEncrypt();
    InitAlias();
    Boot();
    return 0;
}

// 初始化服务端秘钥
void GenerateEncrypt()
{
    FileUtils fileUtils;
    // 判断本地秘钥文件是否生成
    if (fileUtils.Exist(SERVER_PUB_PATH) && fileUtils.Exist(SERVER_PRV_PATH))
    {
        // 读取秘钥保存进应用上下文
        AppContext::Get()->set_server_pub_key(fileUtils.FRead(SERVER_PUB_PATH));
        AppContext::Get()->set_server_prv_key(fileUtils.FRead(SERVER_PRV_PATH));
        return;
    }
    // 生成秘钥文件
    CryptoGraphic cg;
    cg.GenerateRSA(RSA_LENGTH);
    AppContext::Get()->set_server_pub_key(cg.PublicKey());
    AppContext::Get()->set_server_prv_key(cg.PrivateKey());
    fileUtils.FWrite(SERVER_PUB_PATH, cg.PublicKey().c_str(), cg.PublicKey().size());
    fileUtils.FWrite(SERVER_PRV_PATH, cg.PrivateKey().c_str(), cg.PrivateKey().size());
    LOG4CPLUS_INFO(SimpleLogger::Get()->LoggerRef(), "生成服务端本地秘钥");
}

// 初始化日志系统
void InitLogger()
{
    string log_level = "";
    string log_pattern = "%d{%m/%d/%y %H:%M:%S} %p - %m[%l]%n";
    string log_out_path = "log/";
    FileUtils fileUtils;
    fileUtils.MDir(log_out_path.c_str());
    Properties p;
    if (p.Init("logger.properties"))
    {
        if (p.HasKey("level"))
        {
            log_level = p.Key("level");
        }
        if (p.HasKey("pattern"))
        {
            log_pattern = p.Key("pattern");
        }
        if (p.HasKey("out_path"))
        {
            log_out_path = p.Key("out_path");
        }
    }
    // init simple_logger
    SimpleLogger::Get()->Init(log_level.c_str(), log_out_path.c_str(), log_pattern.c_str());
}

// 加载用户别名表
void InitAlias()
{
    AppContext::Get()->LoadAliasTable();
}

// 启动项
void Boot()
{
    int port = 8081;
    int thread_num = 8;
    int client_timeout = 30;
    int stream_port = 8088;
    Properties p;
    if (p.Init("application.properties"))
    {
        if (p.HasKey("port"))
        {
            port = stoi(p.Key("port"));
        }
        if (p.HasKey("thread_num"))
        {
            thread_num = stoi(p.Key("thread_num"));
        }
        if (p.HasKey("client_timeout"))
        {
            client_timeout = stoi(p.Key("client_timeout"));
        }
        if (p.HasKey("stream_port"))
        {
            stream_port = stoi(p.Key("stream_port"));
        }
    }
    AppContext::Get()->set_client_timeout(client_timeout);
    list<thread*> thread_list;
    // 初始化服务端
    SmsServer server(port, thread_num);

    if (server.Init())
    {
        server.Start();
    }
    else
    {
        LOG4CPLUS_ERROR(SimpleLogger::Get()->LoggerRef(), "SmsServer启动失败...应用退出");
        exit(-1);
    }
    thread_list.push_back(server.GetThread());
    // 初始化文件流传输服务
    StreamService service(stream_port, client_timeout / 2);
    if (service.Init())
    {
        // 连接主服务
        if (service.Connect("127.0.0.1", port))
        {
            service.Start();
        }
        else
        {
            LOG4CPLUS_ERROR(SimpleLogger::Get()->LoggerRef(), "StreamService与主服务连接失败...应用退出");
            exit(-1);
        }
    }
    else
    {
        LOG4CPLUS_ERROR(SimpleLogger::Get()->LoggerRef(), "StreamService初始化失败...应用退出");
        exit(-1);
    }
    thread_list.push_back(service.GetThread());
    for(auto iter = thread_list.begin(); iter != thread_list.end(); iter++)
    {
        (*iter)->join();
    }
}
